﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Threading.Tasks;

namespace Crayons
{
    public class PaintCanvas : UserControl
    {
        #region [ Inner Classes ] 
        
        public class PaintObject
        {
            protected Bitmap m_Content;

            protected List<Rectangle> m_Selections;

            protected Point m_Position;
            protected Size m_Size;
            public bool Focus;

            public List<Rectangle> Selections
            {
                get { return m_Selections; }
            }

            public Point Position
            {
                get { return m_Position; }
                set { m_Position = value; }
            }

            public Size Size
            {
                get { return m_Size; }
            }

            public PaintObject()
            {
                byte[] arr = new byte[1024];
                using (MemoryStream fileStream = new MemoryStream(arr))
                {
                    fileStream.Position = 0;
                    Image xxx = Image.FromStream(fileStream);
                }
                m_Content = new Bitmap("C:\\Users\\an.vuongngocduy\\Pictures\\bass10sheet.png");
                m_Size = m_Content.Size;
            }

            public void Draw(Graphics g)
            {          
                g.DrawImageUnscaled(m_Content, m_Position);
                if (Focus)
                {
                    Pen pen = new Pen(new SolidBrush(Color.FromArgb(51, 153, 255)));
                    pen.Width = 1;
                    SolidBrush br = new SolidBrush(Color.FromArgb(64,51, 153, 255));
                    g.FillRectangle(br, new Rectangle(m_Position, m_Size));
                    g.DrawRectangle(pen, new Rectangle(new Point(m_Position.X - 1, m_Position.Y - 1),
                        new Size(m_Size.Width + 2, m_Size.Height + 2)));
                    
                }
            }        
        }
        
        #endregion

        #region [ Fields & Properties ]
        
        protected Bitmap m_BackBuffer;
        protected Graphics m_BackGraph;
        protected List<PaintObject> m_PObjs;
        protected int m_SelectedObjIdx;

        public List<PaintObject> PaintObjects
        {
            get { return m_PObjs;  }
        }

        #endregion

        #region [ Methods ]

        public PaintCanvas()
        {
            Initialize();
            m_PObjs.Add(new PaintObject());
        }
        
        protected void Initialize()
        {
            //init fields
            m_PObjs = new List<PaintObject>();
            m_SelectedObjIdx = -1;

            //init components
            this.DoubleBuffered = true;
            this.Paint += new PaintEventHandler(this.FlexibleViewer_Paint);
            this.Resize += new EventHandler(this.FlexibleViewer_Resize);
            this.MouseDown += new MouseEventHandler(this.PaintCanvas_MouseDown);
            this.MouseMove += new MouseEventHandler(this.PaintCanvas_MouseMove);
        }

        protected void PrepareContent()
        {
            ClearWithCheckerboardPattern();
            foreach (PaintObject po in m_PObjs)
            {
                po.Draw(m_BackGraph);
            }
        }

        protected void ClearWithCheckerboardPattern()
        {
            int numLines = (int)Math.Ceiling((float)(this.Height - 4) / 8.0f);
            Pen dashPen = new Pen(Color.Gray, 8);
            dashPen.DashStyle = DashStyle.Dot;
            m_BackGraph.Clear(Color.White);

            Point[] points = new Point[numLines * 2];
            for (int i = 0; i < numLines; i++)
            {
                int yOffset = i * 8 + 4;
                int xOffset = (i % 2).Equals(0) ? 0 : 8;
                m_BackGraph.DrawLine(dashPen, xOffset, yOffset, this.Width, yOffset);
            }
        }

        #endregion

        #region [ EventHandlers ]

        protected void FlexibleViewer_Load(object sender, EventArgs e)
        {

        }

        protected void FlexibleViewer_Resize(object sender, EventArgs e)
        {
            m_BackBuffer = new Bitmap(this.Width, this.Height);
            m_BackGraph = Graphics.FromImage(m_BackBuffer);
            PrepareContent();
        }

        protected void FlexibleViewer_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImageUnscaled(m_BackBuffer, 0, 0);
        }

        Point delta;

        protected void PaintCanvas_MouseDown(object sender, MouseEventArgs e)
        {
            m_SelectedObjIdx = -1;
            if (e.Button == MouseButtons.Left)
            {
                if (m_SelectedObjIdx < 0)
                {
                    for (int i = 0; i < m_PObjs.Count; i++ )
                    {
                        Rectangle rec = new Rectangle(m_PObjs[i].Position, m_PObjs[i].Size);
                        if (rec.Contains(e.Location))
                        {
                            m_SelectedObjIdx = i;
                            m_PObjs[i].Focus = true;
                            delta.X = e.Location.X - rec.Left;
                            delta.Y = e.Location.Y - rec.Top;
                            break;
                        }
                        else
                        {
                            m_PObjs[i].Focus = false;
                        }
                    }
                }
            }
            PrepareContent();
            this.Invalidate();
        }

        protected void PaintCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (m_SelectedObjIdx >= 0)
                {
                    m_PObjs[m_SelectedObjIdx].Position = new Point(e.Location.X - delta.X, e.Location.Y - delta.Y);
                    PrepareContent();
                }
                this.Invalidate();
            }
        }

        #endregion
    }
}
